/*
	#########################################################
	#			Verzhak										#
	#	e-mail - <verzhak@gmail.com>						#
	#########################################################
	#	Version - 0.0.2										#
	#	Date - 01.03.2009									#
	#	License - GPLv3										#
	#########################################################
*/

// Реализация get_rss.h

#include "get_rss.h"

char *get_rss(void)
{
	char *rez_connect = my_connect();
	char *rez_parse;
	if(rez_connect)
	{
		char *rez_iconv = my_iconv(rez_connect);
		rez_parse = my_parse(rez_iconv);
		FREE(rez_connect);
		FREE(rez_iconv);
	}
	else
		return NULL;	
	return rez_parse;
}

void my_strcat(char *str,const char* from)
{
	unsigned int x,y;
	unsigned int str_len = strlen(str);
	unsigned int from_len = strlen(from);
	for(x=str_len,y=0;x<str_len + from_len;x++,y++)
		str[x] = from[y];
}

char *my_connect(void)
{
	SOCKTYPE sock;
	struct sockaddr_in addr;
	socklen_t addr_len;
	sock = SOCKET(AF_INET,SOCK_STREAM,0);
	// Заметьте, sock в kernel-space и в user-space имеет разные типы
#ifdef MODULE
	if(sock == NULL)
#else
	if(sock < 0)
#endif
		return NULL;

	addr.sin_family = AF_INET;
	addr.sin_port = htons(80);
	addr_len = sizeof(addr);

	if(!INET_ATON(IP_ADRR,&addr.sin_addr))
		return NULL;

	if(!CONNECT(sock,(struct sockaddr*)&addr,addr_len))
	{
		char *rc;
		size_t szr;
		long sm;
		int sc;

		sm = 0;
		sc = 0;
		rc = MALLOC(sizeof(char) * SIZE_RC);
		szr = SEND(sock,MSG,strlen(MSG),0);
		do
		{
			szr = RECV(sock,&rc[sm],SIZE_RC-sm,0);
			sm += szr;
			if(szr == 0)
				sc++;
			else
				sc = 0;
		}
		while(!strstr(rc,"</rss>") && sc < MAX_RECV_BEFORE_CLOSE_CONNECT);
		// </rss> - признак конца ленты
		CLOSE_SOCK(sock);
	
		return rc;
	}
	else
		return NULL;
}

/* Парсим ленту
 * Все последовательности вида "&bla-bla-bla;" преобразуем к " (одной двойной кавычке) */
char *my_parse(const char *str)
{
#define BEGIN_TAG "<item>"
#define END_TAG "</item>"
	int end_tag_len = strlen(END_TAG);
#define TITLE_BEGIN_TAG "<title>"
	int title_begin_tag_len = strlen(TITLE_BEGIN_TAG);
#define TITLE_END_TAG "</title>"
#define DATE_BEGIN_TAG "<pubDate>"
	int date_begin_tag_len = strlen(DATE_BEGIN_TAG);
#define DATE_END_TAG "</pubDate>"
#define DESK_BEGIN_TAG "<description><![CDATA["
	int desk_begin_tag_len = strlen(DESK_BEGIN_TAG);
#define DESK_END_TAG "]]></description>"
#define NEXT "==============================="
	int next_line_len = strlen(NEXT);
#define BR "<br>"
	int br_len = strlen(BR);
#define RPL_SYMB '"'
#define RPL_FIRST "&"
#define BR_NEXT 0
#define RPL_NEXT 1

	char *rez,*begin,*when_title_end,*when_date_end,*when_desk_end,*temp,*temp_p,*begin_br,*begin_rpl,*end;
	unsigned long next;
	temp = MALLOC(sizeof(char)*strlen(str)+1);
	strcpy(temp,str);
	temp_p = temp;
       	begin_br = strstr(temp_p,BR);
	begin_rpl = strstr(temp_p,RPL_FIRST);
	end = NULL;
	// Сначала <br> к '\n', &bla-bla-bla; к '"'
	if((begin_br < begin_rpl || (!begin_rpl)) && begin_br)
	{
		end = begin_br + br_len;
		next = 0;
	}
	else if(begin_rpl)
	{
		end = strstr(begin_rpl,";") + 1;
		next = 1;
	}
	else
		next = 2;
	while((begin_br || begin_rpl) && next < 2)
	{
		if(next == 0)
		{
			begin_br[0] = '\n';
			begin_br[1] = '\0';
		}
		else
		{
			begin_rpl[0] = RPL_SYMB;
			begin_rpl[1] = '\0';
		}
		my_strcat(temp_p,end);

		begin_br = strstr(temp_p,BR);
		begin_rpl = strstr(temp_p,RPL_FIRST);

		if((begin_br < begin_rpl || (begin_rpl)) && begin_br)
		{
			end = begin_br + br_len;
			next = 0;
		}
		else if(begin_rpl)
		{
			end = strstr(begin_rpl,";") + 1;
			next = 1;
		}
		else
			next = 2;
	}
	// Теперь - xml -> красивый списочег (заголовок \n дата \n цитата \n - для каждой цитаты)
	temp_p = temp;
	rez = MALLOC(sizeof(char)*SIZE_REZ);
	begin = strstr(temp_p,BEGIN_TAG);
	end = strstr(temp_p,END_TAG);
	next = 0;
	while(begin)
	{
		char *title_begin,*date_begin,*desk_begin;
		title_begin = strstr(begin,TITLE_BEGIN_TAG);
		if(title_begin)
		{
			title_begin += title_begin_tag_len;
			when_title_end = strstr(begin,TITLE_END_TAG);
			if(when_title_end)
			{
				*(when_title_end-1) = '\0';
				strcat(&rez[next],title_begin);
				strcat(&rez[next],"\n");
				begin = when_title_end;
			};
		}
		date_begin = strstr(begin,DATE_BEGIN_TAG);
		if(date_begin)
		{
			date_begin += date_begin_tag_len;
			when_date_end = strstr(begin,DATE_END_TAG);
			if(when_date_end)
			{
				*(when_date_end-1) = '\0';
				strcat(&rez[next],date_begin);
				strcat(&rez[next],"\n");
				begin = when_date_end;
			};
		}
		desk_begin = strstr(begin,DESK_BEGIN_TAG);
		if(desk_begin)
		{
			desk_begin += desk_begin_tag_len;
			when_desk_end = strstr(begin,DESK_END_TAG);
			if(when_desk_end)
			{
				*(when_desk_end-1) = '\0';
				strcat(&rez[next],desk_begin);
				strcat(&rez[next],"\n");
				begin = when_desk_end;
			};
		}

		strcat(&rez[next],NEXT);
		strcat(&rez[next],"\n");
		next += next_line_len + (title_begin ? strlen(title_begin) : 0) + (date_begin ? strlen(date_begin) : 0) + (desk_begin ? strlen(desk_begin) : 0);

		if(end)
		{
			temp_p = end + end_tag_len;
			begin = strstr(temp_p,BEGIN_TAG);
			end = strstr(temp_p,END_TAG);
		}
		else
			begin = NULL;
	}
	strcat(&rez[next],NEXT);
	strcat(&rez[next],"\n");
	FREE(temp);
	return rez;
}

char *my_iconv(const char *str)
{
#ifndef MODULE
	// Пользуем iconv для перекодировки
	char *rez_p,*rez_p_p,*iconv_rez,*iconv_rez_p;
	size_t rez_size,iconv_rez_size;
	iconv_t iconv_desk;

	rez_p = MALLOC(sizeof(char)*strlen(str)+1);
	strcpy(rez_p,str);
	// На исходную и результирующую строки нужно по дополнительному указателю (они вовсю используются в iconv)
	rez_p_p = rez_p;
	rez_size = strlen(rez_p);
	iconv_rez = MALLOC(sizeof(char)*SIZE_RC);
	iconv_rez_p = iconv_rez;
	iconv_rez_size = SIZE_RC;

	// Вот здесь, собственно, перекодировка
	iconv_desk = iconv_open("UTF-8","CP1251");
	iconv(iconv_desk,&rez_p_p,&rez_size,&iconv_rez_p,&iconv_rez_size);
	iconv_close(iconv_desk);
	// Все. Перекодировка завершена

	FREE(rez_p);
	return iconv_rez;
#else
	//Перекодировка не происходит
	char *rez_p = MALLOC(sizeof(char)*strlen(str)+1);
	strcpy(rez_p,str);
	return rez_p;
#endif
}
